/**
  **************************************************************************
  * @file     i2s.c
  * @version  v1.1.0
  * @date     2025-06-18
  * @brief    i2s初始化配置
  **************************************************************************
  */

/* Includes ------------------------------------------------------------------*/
#include "./i2s/i2s.h"  
#include "./board/bsp.h"

/* Private functions ------------------------------------------------------- */
void (*i2s_tx_callback)(void);          /* I2S TX DMA回调函数指针 */
void (*i2s_rx_callback)(void);          /* I2S RX DMA回调函数指针 */

/**
 * @brief       I2S初始化
 * @param       std             : I2S标准,      0,飞利浦标准;      1,MSB对齐标准(右对齐);  2,LSB对齐标准(左对齐);  3,PCM标准
 * @param       mode            : I2S工作模式,  0,从机发送;        1,从机接收;             2,主机发送;            3,主机接收
 * @param       cpol            : I2S时钟极性   0,时钟低电平有效;   1,时钟高电平有效
 * @param       datalen         : 数据长度      0,16位标准;        1,16位扩展(frame=32bit);2,24位;                3,32位.
 * @param       samplerate		: 采样率, 单位:Hz
 * @retval      无
 */
void iis_init(uint32_t std, uint32_t mode, uint32_t cpol, uint32_t datalen, uint32_t samplerate)
{
	gpio_init_type gpio_init_struct;
	i2s_init_type i2s_init_struct;
	
	crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE);
	crm_periph_clock_enable(CRM_GPIOB_PERIPH_CLOCK, TRUE);
	crm_periph_clock_enable(CRM_GPIOC_PERIPH_CLOCK, TRUE);
	crm_periph_clock_enable(CRM_IOMUX_PERIPH_CLOCK, TRUE);
	crm_periph_clock_enable(CRM_SPI3_PERIPH_CLOCK, TRUE);
	gpio_pin_remap_config(SWJTAG_GMUX_010, TRUE);
	
	gpio_default_para_init(&gpio_init_struct);
	i2s_default_para_init(&i2s_init_struct);
	
	/* master ws pin */
	gpio_init_struct.gpio_out_type       = GPIO_OUTPUT_PUSH_PULL;  
	gpio_init_struct.gpio_pull           = GPIO_PULL_UP;  
	gpio_init_struct.gpio_mode           = GPIO_MODE_MUX;  
	gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
	gpio_init_struct.gpio_pins           = GPIO_PINS_15;
	gpio_init(GPIOA, &gpio_init_struct);

	/* master ck pin */
	gpio_init_struct.gpio_pull           = GPIO_PULL_DOWN;  
	gpio_init_struct.gpio_pins           = GPIO_PINS_3;
	gpio_init(GPIOB, &gpio_init_struct);

	/* master sd pin */ 
	gpio_init_struct.gpio_pull           = GPIO_PULL_UP;   
	gpio_init_struct.gpio_pins           = GPIO_PINS_5;
	gpio_init(GPIOB, &gpio_init_struct);

	/* master mck pin */
	gpio_init_struct.gpio_pins           = GPIO_PINS_7;
	gpio_init(GPIOC, &gpio_init_struct);

	/* configure the SDEXT pin */
	gpio_init_struct.gpio_pull           = GPIO_PULL_NONE;
	gpio_init_struct.gpio_mode           = GPIO_MODE_INPUT;
	gpio_init_struct.gpio_pins           = GPIO_PINS_4;
	gpio_init(GPIOB, &gpio_init_struct);
	
	/* configure the i2s_init_struct */
	i2s_init_struct.audio_sampling_freq = (i2s_audio_sampling_freq_type)samplerate;
	i2s_init_struct.operation_mode = (i2s_operation_mode_type)mode;
	i2s_init_struct.audio_protocol = (i2s_audio_protocol_type)std;
	i2s_init_struct.data_channel_format = (i2s_data_channel_format_type)(datalen + 1);
	i2s_init_struct.clock_polarity = (i2s_clock_polarity_type)cpol;
	i2s_init_struct.mclk_output_enable = TRUE;
	i2s_init(SPI3, &i2s_init_struct);

	/* configure the i2s_init_struct(i2sdext) */
	i2s_init_struct.operation_mode = I2S_MODE_SLAVE_RX;
	i2s_init(I2S3EXT, &i2s_init_struct);
	
	spi_i2s_dma_transmitter_enable(SPI3, TRUE);
	spi_i2s_dma_receiver_enable(I2S3EXT, TRUE);
	
	i2s_enable(SPI3, TRUE);
	i2s_enable(I2S3EXT, TRUE);
}

/**
 * @brief       I2S TX DMA配置
 *  @note       开启DMA传输完成中断
 * @param       buf0 : M0AR地址.
 * @param       num  : 每次传输数据量
 * @retval      无
 */
void i2s_tx_dma_init(uint8_t* buf0, uint16_t num)
{
	dma_init_type dma_init_struct;
	
	crm_periph_clock_enable(CRM_DMA1_PERIPH_CLOCK, TRUE);
	dma_reset(DMA1_CHANNEL1);
	
	dma_flexible_config(DMA1, FLEX_CHANNEL1, DMA_FLEXIBLE_SPI3_TX);
	
	dma_default_para_init(&dma_init_struct);
	
	dma_init_struct.buffer_size = num;
	dma_init_struct.direction = DMA_DIR_MEMORY_TO_PERIPHERAL;
	dma_init_struct.memory_base_addr = (uint32_t)buf0;
	dma_init_struct.memory_data_width = DMA_MEMORY_DATA_WIDTH_HALFWORD;
	dma_init_struct.memory_inc_enable = TRUE;
	dma_init_struct.peripheral_base_addr = (uint32_t)(&(SPI3->dt));
	dma_init_struct.peripheral_data_width = DMA_PERIPHERAL_DATA_WIDTH_HALFWORD;
	dma_init_struct.peripheral_inc_enable = FALSE;
	dma_init_struct.priority = DMA_PRIORITY_HIGH;
	dma_init_struct.loop_mode_enable = TRUE;
	dma_init(DMA1_CHANNEL1, &dma_init_struct);
	
	dma_interrupt_enable(DMA1_CHANNEL1, DMA_FDT_INT, TRUE);
	
	nvic_irq_enable(DMA1_Channel1_IRQn, 2, 0);   /* 抢占2，子优先级0，组1 */
	
	dma_channel_enable(DMA1_CHANNEL1, TRUE);
} 

/**
 * @brief       I2Sext RX DMA配置
 *  @note       开启DMA传输完成中断
 * @param       buf0 : M0AR地址.
 * @param       num  : 每次传输数据量
 * @retval      无
 */
void i2sext_rx_dma_init(uint8_t* buf0, uint16_t num)
{  
    dma_init_type dma_init_struct;
	
	crm_periph_clock_enable(CRM_DMA1_PERIPH_CLOCK, TRUE);
	dma_reset(DMA1_CHANNEL2);
	
	dma_flexible_config(DMA1, FLEX_CHANNEL2, DMA_FLEXIBLE_I2S3EXT_RX);
	
	dma_default_para_init(&dma_init_struct);
	
	dma_init_struct.buffer_size = num;
	dma_init_struct.direction = DMA_DIR_PERIPHERAL_TO_MEMORY;
	dma_init_struct.memory_base_addr = (uint32_t)buf0;
	dma_init_struct.memory_data_width = DMA_MEMORY_DATA_WIDTH_HALFWORD;
	dma_init_struct.memory_inc_enable = TRUE;
	dma_init_struct.peripheral_base_addr = (uint32_t)(&I2S3EXT->dt);
	dma_init_struct.peripheral_data_width = DMA_PERIPHERAL_DATA_WIDTH_HALFWORD;
	dma_init_struct.peripheral_inc_enable = FALSE;
	dma_init_struct.priority = DMA_PRIORITY_HIGH;
	dma_init_struct.loop_mode_enable = TRUE;
	dma_init(DMA1_CHANNEL2, &dma_init_struct);
	
	dma_interrupt_enable(DMA1_CHANNEL2, DMA_FDT_INT, TRUE);
	
	nvic_irq_enable(DMA1_Channel2_IRQn, 3, 0);   /* 抢占3，子优先级0，组2 */
	
	dma_channel_enable(DMA1_CHANNEL2, TRUE);
}
 
/**
 * @brief       I2S TX DMA 中断服务函数
 * @param       无
 * @retval      无
 */
void DMA1_Channel1_IRQHandler(void)
{
    if(dma_flag_get(DMA1_FDT1_FLAG) != RESET) {
		dma_flag_clear(DMA1_FDT1_FLAG);
		i2s_tx_callback(); 				/* 执行回调函数,发送数据等操作在这里面处理 */
  }
}

/**
 * @brief       I2Sext RX DMA 中断服务函数
 * @param       无
 * @retval      无
 */
void DMA1_Channel2_IRQHandler(void)
{
    if(dma_flag_get(DMA1_FDT2_FLAG) != RESET) {
        dma_flag_clear(DMA1_FDT2_FLAG);
        i2s_rx_callback();              /* 执行回调函数,读取数据等操作在这里面处理 */
    }
}

/**
 * @brief       I2S开始播放
 * @param       无
 * @retval      无
 */
void i2s_play_start(void)
{
    spi_i2s_dma_transmitter_enable(SPI3, TRUE);       	/* 开启I2S TX DMA传输 */
}

/**
 * @brief       I2S停止播放
 * @param       无
 * @retval      无
 */
void i2s_play_stop(void)
{
	spi_i2s_dma_transmitter_enable(SPI3, FALSE);		/* 关闭I2S TX DMA传输 */
}

/**
 * @brief       I2S开始录音
 * @param       无
 * @retval      无
 */
void i2s_rec_start(void)
{
    spi_i2s_dma_receiver_enable(I2S3EXT, TRUE);     	/* 开启I2S RX DMA传输 */
}

/**
 * @brief       I2S停止录音
 * @param       无
 * @retval      无
 */
void i2s_rec_stop(void)
{
    spi_i2s_dma_receiver_enable(I2S3EXT, FALSE);   		/* 关闭I2S RX DMA传输 */
}

